#include "structdef.h"
#include "lex.yy.c"
#include "povparser.h"

#include "../../geom/PolyModel.h"
#include "../../geom/PolyMesh.h"
#include "../../geom/MeshPoint.h"
#include "../../geom/Point3D.h"

std::string lastName;

using namespace std;
using namespace geom;

PolyModel * readPOVFile(string filename, string baseName)
{
	FILE * f = fopen(filename.c_str(),"r");
	if(f==NULL)
		return NULL;
	yyrestart(f);
	PolyModel * o = new PolyModel();
	o->setName(baseName);
	PolyMesh * m;
	struct Token t;
	do{
		t = readNextToken();
		switch(t.token)
		{
			case TOKEN_DECLARATION_NAME:
				{
					lastName = std::string(t.text);
				}
				break;
			case TOKEN_MESH_START:
				{
					m=readMesh();
					m->setName(lastName);
					o->addMesh(*m);
					delete m;
				}
				break;
		}
		t.clean();
	}
	while(t.token!=TOKEN_FIN);

	return o;
}

PolyMesh * readMesh()
{
	struct Token t;
	util::Triplet<MeshPoint> tri;
	PolyMesh * m = new PolyMesh();
	do{
		t=readNextToken();
		switch(t.token)
		{
			case TOKEN_TRIANGLE_START:
				{
					tri = readTriangle();
					m->addTriangle(tri);
				}
				break;

			case TOKEN_ROTATE_X:
				{
					float rotx = readRotation();
					//m->setRotX(rotx);
				}
				break;

			case TOKEN_ROTATE_Y:
				{
					float roty = readRotation();
					//m->setRotY(roty);
				}
				break;

			case TOKEN_ROTATE_Z:
				{
					float rotz = readRotation();
				//	m->setRotZ(rotz);
				}
				break;
				// TODO añadir el TOKEN de textura, para crear las texturas del arbol 

			default:
				{
					/*       if(t.mustFree)
							 printf("read token: %s\n",t.text);
							 else
							 printf("read token: %i\n",t.token);
					 */
				}
		}
		t.clean();

	}while(t.token!=TOKEN_MESH_END && t.token!=TOKEN_FIN);
	return m;
}

Triplet<MeshPoint> readTriangle()
{
	struct Token t;
	Triplet<MeshPoint> tri;
	Point3D p;

	int readPoints = 0;

	do{
		t=readNextToken();
		if(t.token == TOKEN_BEGIN_POINT)
		{
			if(readPoints>3)
			{
				//TODO lanzar una excepcion
			}
			p = readPoint();
			p.y = -p.y; // the Y value is upside down in the inc files
			tri[readPoints].p = p;
			tri[readPoints].AOFactor = 0.5;
			++readPoints;
		}

		t.clean();
	}
	while(t.token!=TOKEN_TRIANGLE_END);


	return tri;
}

Point3D readPoint()
{
	int floatsRead=0;
	Point3D p;
	p.x=0;
	p.y=0;
	p.z=0;
	struct Token t;

	do{
		t=readNextToken();
		if(t.token != TOKEN_NUMBER && t.token != TOKEN_IRRELEVANT || floatsRead>3 )
		{
			//TODO añadir aqui una excepcion
		}
		else
		{
			p.v[floatsRead] = t.f;
			++floatsRead;
		}
	}
	while(t.token != TOKEN_END_POINT);
	return p;
}

float readRotation()
{
	struct Token t;
	t=readNextToken();
	t.clean();
	return t.f;
}

